package com.example.onlinemonitoring.comCenter;

import com.example.onlinemonitoring.Util.CRC16;
import com.example.onlinemonitoring.Util.CommPortManager;
import com.example.onlinemonitoring.Util.HexUtil;
import com.example.onlinemonitoring.model.Wxwssensor;
import com.example.onlinemonitoring.model.Wxwshistory;
import com.example.onlinemonitoring.model.Appdevice;
import com.example.onlinemonitoring.model.Sf6sensor;
import com.example.onlinemonitoring.serviceImpl.WxwssensorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Scope;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/*这里beanName需要和数据库Appdevice中的simple对应并加上Com,不对应请自行修改
    例:simple:dlhl
    @Service("dlhlCom")
*/
@Service("wxwsCom")
@Scope("prototype")
public class WxwsCom extends CommPortManager {
        @Autowired
        private WxwssensorServiceImpl wxwssensorServiceImpl;

        @Override
        public void receiveData(String str) {
            str = str.toUpperCase();
            setText(str);
            switch (ad.getBrand()) {
                case "透传":
                    TC(str);
                    break;
                case "ModBus":
                    ModBus(str);
                    break;
                default:
                    return;
            }
        }
        public void TC(String str) {
            try {

                //条件判断自己写
                String addrstr = str.substring(0, 2);
                Integer addrint = parseHex4(addrstr);
                if (str.length() < 12)
                return;
                reSend[addrindex] = 0;
                addrindex++;
                float pressure = 0, temperature = 0, relativeHumidity = 0, density = 0, pressure20 = 0,
                waterVaporPartialPressure = 0, dewPoint = 0, PPMVolumeFraction = 0;
                float batteryamount=0;
                pressure = parseHex4(str.substring(16, 20))* 0.0001f;
                temperature = parseHex4(str.substring(20, 24)) * 0.1f;
                PPMVolumeFraction = parseHex4(str.substring(24, 28));
                pressure20 = parseHex4(str.substring(28, 32))* 0.0001f;   
                density = parseHex4(str.substring(32, 36)) * 0.01f;            
                dewPoint = parseHex4(str.substring(36, 40)) * 0.1f;
                waterVaporPartialPressure = parseHex4(str.substring(40, 44)) * 0.1f;
                batteryamount= parseHex4(str.substring(44, 48)) *0.01f;
                //relativeHumidity = parseHex4(str.substring(58, 62));
                SensorData(addrint, new Date(), pressure, temperature, density, waterVaporPartialPressure,
                        dewPoint, PPMVolumeFraction, pressure20,batteryamount);
            } catch (Exception ex) {
                ex.printStackTrace();
                setText("从设备返回的数据有误！请检查串口！");
            }
        }
        public void ModBus(String str) {
            try {

                //条件判断自己写
                String addrstr = str.substring(0, 2);
                Integer addrint = parseHex4(addrstr);
                if (str.length() < 12)
                return;
                reSend[addrindex] = 0;
                addrindex++;
                float pressure = 0, temperature = 0, relativeHumidity = 0, density = 0, pressure20 = 0,
                waterVaporPartialPressure = 0, dewPoint = 0, PPMVolumeFraction = 0;
                float batteryamount=0;
                pressure = parseHex4(str.substring(6, 10))* 0.0001f;
                temperature = parseHex4(str.substring(10, 14)) * 0.1f;
                PPMVolumeFraction = parseHex4(str.substring(14, 18));
                pressure20 = parseHex4(str.substring(18, 22))* 0.0001f;   
                density = parseHex4(str.substring(22, 26)) * 0.01f;            
                dewPoint = parseHex4(str.substring(26, 30)) * 0.1f;
                waterVaporPartialPressure = parseHex4(str.substring(30, 34)) * 0.1f;
                batteryamount= parseHex4(str.substring(34, 38)) *0.01f;
                //relativeHumidity = parseHex4(str.substring(58, 62));
                SensorData(addrint, new Date(), pressure, temperature, density, waterVaporPartialPressure,
                        dewPoint, PPMVolumeFraction, pressure20,batteryamount);
            } catch (Exception ex) {
                ex.printStackTrace();
                setText("从设备返回的数据有误！请检查串口！");
            }
        }
    void SensorData(int addrint, Date nowtime, float pressure, float temperature,
            float density, float waterVaporPartialPressure, float dewPoint, float PPMVolumeFraction, float pressure20,float batteryamount) {
        // if (relativeHumidity <= 0.5) {
        //     Random rd = new Random();
        //     relativeHumidity = (float) 0.01 * (rd.nextInt(20) + 80);
        //     float temp = (10.286f * temperature + 661.13f) / (temperature + 273.3f);
        //     double ps = Math.pow((double) 0, (double) temp) / 1000000;
        //     float pw = (float) ps * relativeHumidity * 0.01f;
        //     temp = 0.66077f + 7.5f * temperature / (237.3f + temperature)
        //             + (float) Math.log10((double) relativeHumidity) - 2f;
        //     dewPoint = ((0.66077f - temp) * 237.3f) / (temp - 8.16077f);
        //     PPMVolumeFraction = pw / pressure * 1000000;
        // }
        if (PPMVolumeFraction > 99999)
            PPMVolumeFraction = 99999;
        setText("解析日新SF6微水密度通信数据：站点号：1 监测点" + addrint);
        setText("压力：" + pressure + "MPa");
        setText("压力(20℃)：" + pressure20 + "MPa");
        setText("温度：" + temperature + "℃");
       // setText("相对湿度：" + relativeHumidity + "%");
        setText("密度：" + density + "kg/m³");
        setText("露点：" + dewPoint + "℃");       
        setText("常压露点(20℃)：" + waterVaporPartialPressure + "℃");
        setText("微水体积分数：" + PPMVolumeFraction + "ppmV");
        setText("电池电量" + batteryamount + "V");

        Wxwssensor ws = new Wxwssensor();
        ws.setStationid(ad.getStationid());
        ws.setDevicegroup(ad.getDevicegroup());
        ws.setDeviceaddr(addrint);
        ws = wxwssensorServiceImpl.getModel(ws);

        if (ws == null) {
            setText("当前数据库无监测点：" + addrint + " ！ 请先添加该监测点！");
            return;
        }
        ws.setLasttemperature(temperature);
       // ws.setLasthumidity(relativeHumidity);
        ws.setLastpressure(pressure);
        ws.setLastpressure20(pressure20);
        ws.setLastdensity(density);
        ws.setLastdaiya(dewPoint);
        ws.setLastchangya(waterVaporPartialPressure);
        ws.setLastppm(PPMVolumeFraction);
        ws.setLastbatteryamount(batteryamount);
        ws.setDeviceaddr(addrint);
        ws.setStationid(ad.getStationid());
        ws.setLastdatatime(nowtime);

        AddAndUpdate(ws);
    }
        @Transactional
        private void AddAndUpdate(Wxwssensor record) {
            int alarmLevel = 0;// 报警等级
            String alarmMessage = "";// 报警消息
            //报警逻辑
        List<Integer> array = new ArrayList<>();
        record.setLastchangyaalarmstatus(
                GetAlarmStatus(isnull(record.getLastchangya()), isnull(record.getChangyaalarmvalue()),
                        isnull(record.getChangyaalarmrelievevalue()), isnull(record.getChangyawarnvalue()),
                        isnull(record.getChangyawarnrelievevalue()),
                        isnull(record.getLastchangyaalarmstatus()), true, "常压露点", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastchangyaalarmstatus(), "常压露点");
        array.add(record.getLastchangyaalarmstatus());
        
        record.setLastdaiyaalarmstatus(
                GetAlarmStatus(isnull(record.getLastdaiya()), isnull(record.getDaiyaalarmvalue()),
                        isnull(record.getDaiyaalarmrelievevalue()), isnull(record.getDaiyawarnvalue()),
                        isnull(record.getDaiyawarnrelievevalue()),
                        isnull(record.getLastdaiyaalarmstatus()), true, "带压露点", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastdaiyaalarmstatus(), "带压露点");
        array.add(record.getLastdaiyaalarmstatus());

        record.setLastpressure20alarmstatus(
                GetAlarmStatus(isnull(record.getLastpressure20()), isnull(record.getPressure20alarmvalue()),
                        isnull(record.getPressure20alarmrelievevalue()), isnull(record.getPressure20warnvalue()),
                        isnull(record.getPressure20warnrelievevalue()),
                        isnull(record.getLastpressure20alarmstatus()), false, "20℃压力", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastpressure20alarmstatus(), "20℃压力");
        array.add(record.getLastpressure20alarmstatus());
    

        record.setLastdensityalarmstatus(GetAlarmStatus(isnull(record.getLastdensity()),
                isnull(record.getDensityalarmvalue()),
                isnull(record.getDensityalarmrelievevalue()), isnull(record.getDensitywarnvalue()),
                isnull(record.getDensitywarnrelievevalue()),
                isnull(record.getLastdensityalarmstatus()), false, "密度", record.getDevicegroup(),
                record.getDeviceaddr(), record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastdensityalarmstatus(), "密度");
        array.add(record.getLastdensityalarmstatus());
        // record.setLasthumidityalarmstatus(
        //         GetAlarmStatus(isnull(record.getLasthumidity()), isnull(record.getHumidityalarmvalue()),
        //                 isnull(record.getHumidityalarmrelievevalue()), isnull(record.getHumiditywarnvalue()),
        //                 isnull(record.getHumiditywarnrelievevalue()),
        //                 isnull(record.getLasthumidityalarmstatus()), true, "湿度", record.getDevicegroup(),
        //                 record.getDeviceaddr(),
        //                 record.getPointname()));
        // alarmMessage += GetAlarmMessage(record.getLasthumidityalarmstatus(), "湿度");
        // array.add(record.getLasthumidityalarmstatus());
        record.setLastppmalarmstatus(GetAlarmStatus(isnull(record.getLastppm()), isnull(record.getPpmalarmvalue()),
                isnull(record.getPpmalarmrelievevalue()), isnull(record.getPpmwarnvalue()),
                isnull(record.getPpmwarnrelievevalue()),
                isnull(record.getLastppmalarmstatus()), true, "微水", record.getDevicegroup(), record.getDeviceaddr(),
                record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastppmalarmstatus(), "微水");
        array.add(record.getLastppmalarmstatus());
        record.setLastpressurealarmstatus(
                GetAlarmStatus(isnull(record.getLastpressure()), isnull(record.getPressurealarmvalue()),
                        isnull(record.getPressurealarmrelievevalue()), isnull(record.getPressurewarnvalue()),
                        isnull(record.getPressurewarnrelievevalue()),
                        isnull(record.getLastpressurealarmstatus()), false, "压力", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastpressurealarmstatus(), "压力");
        array.add(record.getLastpressurealarmstatus());

        record.setLasttemperaturealarmstatus(
                GetAlarmStatus(isnull(record.getLasttemperature()), isnull(record.getTemperaturealarmvalue()),
                        isnull(record.getTemperaturealarmrelievevalue()), isnull(record.getTemperaturewarnvalue()),
                        isnull(record.getTemperaturewarnrelievevalue()),
                        isnull(record.getLasttemperaturealarmstatus()), true, "温度", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLasttemperaturealarmstatus(), "温度");
        array.add(record.getLasttemperaturealarmstatus());
        alarmLevel = HexUtil.MAX(array);
            record.setLastalarmlevel(alarmLevel);
            record.setLastalarmmessage(alarmMessage);
            record.setLastcommunicationstatus(0);
            record.setLastdatatime(new Date());
            record.setLasthisdatatime(addHistory(record));
            if ( wxwssensorServiceImpl.Update(record, false) == 0) {
                setText("更新实时数据失败，请检查数据库连接");
            }
        }
        private Date addHistory(Wxwssensor sensor) {
            if (sensor != null) {
                if (sensor.getLasthisdatatime() == null) {
                    add(sensor);
                    return new Date();
                } else {
                    long lasttime = 0;
                    long nowtime = 0;
                    try {
                        lasttime = HexUtil.todate(sensor.getLasthisdatatime()).getTime();
                        nowtime = HexUtil.todate(new Date()).getTime();
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    int timersp = 60000;
                    if (sensor.getLastalarmlevel() != 0) {
                        timersp = ad.getHisalarmtimersp()*1000;
                    } else {
                        timersp = ad.getHistimersp()*1000;
                    }
                    if (lasttime + timersp < nowtime) {
                        add(sensor);
                        return new Date();
                    }
                }
            }
            return null;
        }

        private void add(Wxwssensor sensor) {
            Wxwshistory his = new Wxwshistory();
            his.setDeviceaddr(sensor.getDeviceaddr());
            his.setDevicegroup(sensor.getDevicegroup());
            his.setAlarmlevel(sensor.getLastalarmlevel());
            his.setAlarmmessage(sensor.getLastalarmmessage());
            his.setDatatime(sensor.getLastdatatime());
            his.setPointname(sensor.getPointname());
            his.setStationid(sensor.getStationid());
            //需要添加自己定义的属性
            his.setChangya(sensor.getLastchangya());
            his.setChangyaalarmstatus(sensor.getLastchangyaalarmstatus());
            his.setDaiya(sensor.getLastdaiya());
            his.setDaiyaalarmstatus(sensor.getLastdaiyaalarmstatus());
            his.setDensity(sensor.getLastdensity());
            his.setDensityalarmstatus(sensor.getLastdensityalarmstatus());
            //his.setHumidity(sensor.getLasthumidity());
            //his.setHumidityalarmstatus(sensor.getLasthumidityalarmstatus());
            his.setPpm(sensor.getLastppm());
            his.setPpmalarmstatus(sensor.getLastppmalarmstatus());
            his.setPressure(sensor.getLastpressure());
            his.setPressurealarmstatus(sensor.getLastpressurealarmstatus());
            his.setPressure20(sensor.getLastpressure20());
            his.setPressure20alarmstatus(sensor.getLastpressure20alarmstatus());
            his.setStandby(sensor.getLaststandby());
            his.setTemperature(sensor.getLasttemperature());
            his.setTemperaturealarmstatus(sensor.getLasttemperaturealarmstatus());
            wxwssensorServiceImpl.Add(his);
        }


        @Async("threadPool")
        public void startSendThread(Appdevice Appdevice) throws Exception {
            checkType = "crc16";
            issend.put(Thread.currentThread().getId(), true);
            String cstr = "";
            String cmdtype = "";
            String nametype = "";
            for (addrindex = 0;addrindex < Appdevice.getAddrmax(); addrindex++)
            {
                wxwssensorServiceImpl.UpdateStatus(ad, addrindex,1);
                reSend[addrindex] = 0;
            }
            int timersp = (int) Math.round(Appdevice.getTimersp() * 1000);
            while (issend.get(Thread.currentThread().getId()) != null) {
                if (addrindex > Appdevice.getAddrmax() || addrindex < Appdevice.getAddrmin())
                    addrindex = Appdevice.getAddrmin();
                cstr = String.format(Appdevice.getCmd(), String.format("%02X", addrindex));
                                if (checkType.equals("crc16")) {
                    cstr = cstr + CRC16.calcCrc16(cstr);
                }
                try {
                    if(ad.getBrand().equals("ModBus"))
                        Send(cstr);
                } catch (Exception EX) {
                     setText(EX.toString());
                }
                if(ad.getBrand().equals("ModBus"))
                {
                    reSend[addrindex]++;
                    if (reSend[addrindex] > 3) {
                    wxwssensorServiceImpl.UpdateStatus(ad, addrindex,1);
                    reSend[addrindex] = 0;
                    addrindex++;
                    }                   
                }

                Thread.sleep(timersp);
            }
        }

        // @Async("threadPool")
        // public void startReceiveThread(){
        //     isrecv.put(Thread.currentThread().getId(), true);
        //     while (isrecv.get(Thread.currentThread().getId()) != null) {
        //         //这里根据实际协议替换,解析方法recvCrc16;recvSum();
        //         recv();
        //         try {
        //             Thread.sleep(interval);
        //         } catch (InterruptedException e) {
        //             e.printStackTrace();
        //         }
        //     }
        // }
}
